﻿using System;


namespace DailyFx
{

	public struct Bar : IVariant, ITick
	{
		// public Bar()
		// {
			/** Intended to empty of all fields */
		// }


        /// Intrinsic Property
        /// 

		/// <summary>
		///     Gets or sets time point,  Mainly for Indexing & Plotting .
		/// </summary>
		public DateTime Tick
		{
			get;
			set;
		}
		/// <summary>
		///     Gets or sets last closing price .
		/// </summary>
		public Decimal LastPx
		{
			get;
			set;
		}
		/// <summary>
		///     Gets or sets open price .
		/// </summary>
		public Decimal Open
		{
			get;
			set;
		}
		/// <summary>
		///     Gets or sets high price .
		/// </summary>
		public Decimal High
		{
			get;
			set;
		}
		/// <summary>
		///     Gets or sets low price .
		/// </summary>
		public Decimal Low
		{
			get;
			set;
		}
		/// <summary>
		///     Gets or sets trading volume .
		/// </summary>
		public Decimal Vol
		{
			get;
			set;
		}

        /// 
        ///  end of Intrinsic Property


		public FieldMask FieldMask
		{
			get;
			set;
		}

        /// Derived Property
        ///

        public Decimal Typical
        {
            get
            {
                return Math.Round( (High + Low + LastPx) / 3, 5);
            }
        }
        public Decimal Weighted
        {
            get
            {
                return Math.Round( (High + Low + 2 * LastPx ) / 4, 5);
            }
        }
        public Decimal Median
        {
            get
            {
                return Math.Round( (High + Low) / 2, 5);
            }
        }

        /// 
        ///  end of Derived Property



        public Int32 Rank
        {
            get { return 5; }
        }

        public Int32 RankEx
        {
            get { return 8; }
        }


		public decimal this[FieldMask field]
		{
			get
            {
                switch ( field )
                {
                    case FieldMask.C:	return this.LastPx	;
                    case FieldMask.O:	return this.Open	;
                    case FieldMask.H:	return this.High	;
                    case FieldMask.L:	return this.Low		;
                    case FieldMask.VOL: return this.Vol		;

                    case FieldMask.TP:	return this.Typical	;
                    case FieldMask.WP:	return this.Weighted;
                    case FieldMask.MP:	return this.Median	;

                    // i think this is impossible ??
                    default: return 0.0m;
                }
            }
			set
			{
 				switch ( field )
                {
                    case FieldMask.C:	this.LastPx = value; break;
                    case FieldMask.O:	this.Open	= value; break;
                    case FieldMask.H:	this.High	= value; break;
                    case FieldMask.L:	this.Low	= value; break;
                    case FieldMask.VOL: this.Vol	= value; break;

                    // derived property read-only 
                    default:
                        // throw new ArgumentException ("Cannot modify Unknown or Readonly property .")
                        break;
                }
			}
		}

        public Decimal this [ Int32 index ]
        {
            get
            {
				return this[ (FieldMask)(1 << index)];
            }
            set
            {
				this[ (FieldMask)(1 << index)] = value ;
			}
        }
       

        public Decimal this [ String field ] 
        {
            get 
            {
                FieldMask fimsk = FieldMask.Unknown;
				if ( System.Enum.TryParse( field, out fimsk) )
				{
					return this [ fimsk];
				}

				return 0.0m;
            }
           
        }

       

    }

}
